package com.captcha;

import com.captcha.generator.AbstractCaptcha;
import com.captcha.generator.gif.AnimatedGifEncoder;
import com.captcha.utils.RandomUtils;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.ImagingOpException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

/**
 * @Author: 随风飘的云
 * @Description: gif图片格式生成器
 * @Date: 2022/3/7 13:12
 * @Modified By:
 */
public class GifCaptcha extends AbstractCaptcha{

    //量化器取样间隔 - 默认是10ms
    private int quality = 10;
    // 帧循环次数
    private int repeat = 0;
    // 帧延迟
    private int delay = 200;

    public void createGif(String text){
        final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        // 创建GIF编码器
        AnimatedGifEncoder gifEncoder = new AnimatedGifEncoder();
        // 获取生成的字符
        gifEncoder.start(outputStream);
        //设置量化器取样间隔
        gifEncoder.setQuality(quality);
        // 设置帧延迟
        gifEncoder.setDelay(delay);
        // 设置帧循环次数
        gifEncoder.setRepeat(repeat);
        BufferedImage image;
        char[] strs = text.toCharArray();
        // 创建每个字符需要的颜色
        Color[] fontColor = new Color[strs.length];
        for (int i = 0; i < strs.length; i++) {
            // 获取颜色
            fontColor[i] = RandomUtils.randomColor();
            // 生成图片帧
            image = createImageOfGif(fontColor, strs, i);
            // 添加图片帧
            gifEncoder.addFrame(image);
            // 清空
            image.flush();
        }
        // 结束
        gifEncoder.finish();
        this.imageBytes = outputStream.toByteArray();
        try {
            outputStream.close();
        } catch (IOException e) {
            throw new ImagingOpException("Image output stream close failed");
        }
    }

    private BufferedImage createImageOfGif(Color[] fontColor, char[] strs, int flag){
        // 获取图片基本参数
        int width = getConfig().getWidth();
        int height = getConfig().getHeight();

        // 设置透明度
        AlphaComposite ac;

        final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = image.createGraphics();

        // 填充背景
        FillBackGround(graphics2D, width, height);

        // 抗锯齿
        graphics2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        // 设置字体
        setImageFont(graphics2D);

        // 画干扰圆
        drawCircle(getConfig().getNoiseNumber(), graphics2D);

        // 画干扰线
        drawBasselLine(getConfig().getShadeNumber(), graphics2D);

        // 每一个字符所占的宽度
        int fontWidth = width / strs.length;

        // 获取字体的规格
        FontMetrics fontMetrics = graphics2D.getFontMetrics();

        // 字符的左右边距
        int fontSpace = (fontWidth - (int) fontMetrics.getStringBounds("W", graphics2D).getWidth()) / 2;

        for (int i = 0; i < strs.length; i++) {
            // 设置透明度
            ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, getAlpha(strs.length, flag, i));
            graphics2D.setComposite(ac);

            // 设置字体颜色
            graphics2D.setColor(fontColor[i]);

            // 文字的纵坐标
            int fontY = height - ((height - (int) fontMetrics.getStringBounds(String.valueOf(strs[i]), graphics2D).getHeight()) >> 1);

            // 画内容到图片上
            graphics2D.drawString(String.valueOf(strs[i]), i * fontWidth + fontSpace + 5, fontY - 5);
        }

        // 填充边框
        if(getConfig().isBorder()){
            setImageBoard(graphics2D);
        }
        graphics2D.dispose();
        return image;
    }

    /**
     * 获取透明度,从0到1,自动计算步长
     *
     * @return float 透明度
     */
    private float getAlpha(int v, int i, int j) {
        int num = i + j;
        float r = (float) 1 / v;
        float s = (v + 1) * r;
        return num > v ? (num * r - s) : num * r;
    }
}
